package xyz.hubery.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.util.CollectionUtils;
import xyz.hubery.domain.SysMenu;
import xyz.hubery.domain.SysPrivilege;
import xyz.hubery.domain.SysRoleMenu;
import xyz.hubery.domain.SysUserRole;
import xyz.hubery.mapper.SysMenuMapper;
import xyz.hubery.service.*;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService{

    @Autowired
    private SysUserRoleService userRoleService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysPrivilegeService privilegeService;

    @Override
    public List<SysMenu> getMenusByUserId(Long id) {
        // 首先判断该用户是否为超级管理员，是的话查询所有菜单
        if(sysRoleService.isSuperAdmin(id)) {
            return this.list();
        }
        // 1、根据用户id查询其角色id列表
        QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",id);
        List<Long> roleIds = userRoleService.list(wrapper).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        // 2、根据角色id查询菜单列表
        List<SysMenu> menus = new ArrayList<>();
        Set<Long> set = new HashSet<>();
        for (Long roleId : roleIds) {
            QueryWrapper<SysRoleMenu> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("role_id",roleId);
            List<SysRoleMenu> roleMenus = sysRoleMenuService.list(wrapper1);
            for (SysRoleMenu roleMenu : roleMenus) {
                Long menuId = roleMenu.getMenuId();
                if(set.contains(menuId)) {
                    continue;
                }
                set.add(menuId);
                SysMenu menu = this.getById(menuId);
                menus.add(menu);
            }
        }
        return menus;
    }


    @Override
    public List<SysMenu> getChildMenusByParentId(Long parentId) {
        // 查询子菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        if(parentId == null) { //查询顶级菜单
            wrapper.isNull(SysMenu::getParentId);
        }else{
            wrapper.eq(SysMenu::getParentId,parentId);
        }
        List<SysMenu> subMenus = this.list(wrapper);
        if(CollectionUtils.isEmpty(subMenus)) { // 没有子菜单，说明是最后一层菜单了
            return subMenus;
        }
        for (SysMenu subMenu : subMenus) { // 查询子菜单的子菜单
            // 设置每个菜单的唯一key值(方便前端显示
            subMenu.setMenuKey(subMenu.getMenuKey());

            List<SysMenu> subSubMenus = getChildMenusByParentId(subMenu.getId());
            subMenu.setChilds(subSubMenus);
        }
        return subMenus;
    }

    @Override
    public void querySubMenuPrivileges(List<SysMenu> menus,Long roleId) {
        // 获取叶子菜单列表
        List<SysMenu> leafMenus = new ArrayList<>();
        for (SysMenu menu : menus) {
            extratLeafMenu(menu,leafMenus);
        }

        // 查询所有的权限列表
        List<SysPrivilege> privilegeList = privilegeService.findPrivilegeByRoleId(roleId);

        // 为每个叶子菜单添加权限
        for (SysMenu leafMenu : leafMenus) {
            List<SysPrivilege> menuPrivileges = new ArrayList<>();
            for (SysPrivilege privilege : privilegeList) {
                if(Objects.equals(privilege.getMenuId(), leafMenu.getId())) {
                    menuPrivileges.add(privilege);
                }
            }
            leafMenu.setPrivileges(menuPrivileges);
        }
    }


    private void extratLeafMenu(SysMenu menu, List<SysMenu> leafMenus) {
        if(menu == null) {
            return;
        }
        if (CollectionUtils.isEmpty(menu.getChilds())) { // 没有子菜单说明当前是叶子节点
            leafMenus.add(menu);
            return;
        }

        // 递归遍历当前菜单的子菜单
        for (SysMenu child : menu.getChilds()) {
            extratLeafMenu(child,leafMenus);
        }
    }


}
